package cn.com.callback

import cn.com.callback.CallBackInvoke
import cn.com.elite.EliteBean
import cn.com.elite.Util
import cn.com.kh.HttpClientUtil
import cn.com.kh.KHDBConfig
import cn.com.kh.KHUtil
import net.sf.json.JSONArray
import net.sf.json.JSONObject
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.content.ContentBody
import org.apache.http.entity.mime.content.FileBody
import org.apache.http.entity.mime.content.StringBody
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.protocol.HTTP
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import javax.activation.MimetypesFileTypeMap

public class autoFaxSend implements CallBackInvoke {
    private static final Logger log = LoggerFactory.getLogger(autoFaxSend.class);

    public void doCallBack(EliteBean eliteBean, String callBack, Map map, String paramString) {

        log.debug('开始查找待发传真任务......');

        doSendFax(eliteBean);
        doFaxResult(eliteBean);

    }

    // 发送传真
    public static void doSendFax(EliteBean eliteBean) {

        // 获取token
        JSONObject getTokenJson = JSONObject.fromObject(Util.doHttpGet(KHDBConfig.getAPIURL(eliteBean, "Local_Token"), "UTF-8", 12000, 0));
        String access_token = getTokenJson.getJSONObject("data").getString("access_token");
        log.debug("获取调用Token:" + access_token);

        // 查找待发送任务
        String selectSQL = '''Select R1.Rec_Guid, R1.Subject, R1.Faxnumber, R1.Faxnumberext, R1.Rawfile, R1.Firstpage, R1.Lastpage, R1.Qr, R2.Sms_Guid
                              From Kh_Sw_Sendfax R1
                              Left Join Waterofffaxbatch R2
                                On R1.Sms_Guid = R2.Sms_Guid
                             Where R1.Status In (0, -1)
                               And R1.Send_Count < R1.Send_Countlimit
                               And Isnull(R1.Expectedstartdate, Getdate()) <= Getdate()
                               And R2.Status = 1
                             Order By R1.Expectedstartdate, R1.Createddate''';
        List getSmsSelectSQL = eliteBean.chaxun_sql(selectSQL, "dataSource");
        log.debug("SQL获取待发送数据量:" + getSmsSelectSQL.size());

        for (int i = 0; i < getSmsSelectSQL.size(); i++) {

            Map selectResultcm = getSmsSelectSQL.get(i);
            log.debug("当前待发送数据：", selectResultcm);

            String Rec_Guid = selectResultcm.get("Rec_Guid");
            String Sms_Guid = selectResultcm.get("Sms_Guid");

            // 发送
            String sendResult = uploadFile(eliteBean, KHDBConfig.getAPIURL(eliteBean, "FAX-sendURL"), access_token, selectResultcm);
            log.debug("传真-调用发送接口【结果】:" + sendResult);

            JSONObject sendJson = new JSONObject();
            int failCode = -99;
            String failDesc = "";
            try {
                sendJson = JSONObject.fromObject(sendResult);

                failCode = sendJson.getInt("code");
                failDesc = sendJson.getString("msg");
            } catch (Exception e) {
                failCode = -99;
                failDesc = "内部调用传真系统接口返回异常-详情请查看日志";
                log.error(failDesc + e.getMessage());
            }
            if (failCode == 1) {
                // 发送成功
                String faxid = sendJson.getJSONObject("data").getString("sid");
                eliteBean.update("Update Kh_Sw_Sendfax Set Status = '1', faxid = '" + faxid + "', send_code = '" + failCode + "', send_description = '" + failDesc + "', send_json = '" + sendResult + "', send_count = send_count + 1, lasttrydatetime = Getdate() Where Rec_Guid = '" + Rec_Guid + "'", "dataSource");
            } else {
                // 发送失败
                eliteBean.update("Update Kh_Sw_Sendfax Set Status = Case When send_count + 1 >= send_countlimit Then '-1' Else Status End, send_code = '" + failCode + "', send_description = '" + failDesc + "', send_json = '" + sendResult + "', send_count = send_count + 1, Lasttrydatetime = Getdate() Where Rec_Guid = '" + Rec_Guid + "'", "dataSource");
            }

            List getallSelectSQL = eliteBean.chaxun_sql('''Select Count(*) As Allnum,
                                           Sum(Case
                                                 When R2.Status In (0, -1) And R2.Send_Count < R2.Send_Countlimit And Isnull(R2.Expectedstartdate, Getdate()) <= Getdate() And R1.Status = 1 Then
                                                  1
                                                 Else
                                                  0
                                               End) As Nosendnum
                                      From Waterofffaxbatch R1
                                      Left Join Kh_Sw_Sendfax R2
                                        On R1.Sms_Guid = R2.Sms_Guid
                                     Where R1.Sms_Guid = \'''' + Sms_Guid + '''\'''', "dataSource");
            if (getallSelectSQL.size() > 0 && getallSelectSQL.get(0).get("Nosendnum") == 0) {
                eliteBean.update("Update Waterofffaxbatch Set Status = 2 Where Sms_Guid = '" + Sms_Guid + "'", "dataSource");
            }

        }

    }

    // 获取发送结果
    public static void doFaxResult(EliteBean eliteBean) {

        // 获取token
        JSONObject getTokenJson = JSONObject.fromObject(Util.doHttpGet(KHDBConfig.getAPIURL(eliteBean, "Local_Token"), "UTF-8", 12000, 0));
        String access_token = getTokenJson.getJSONObject("data").getString("access_token");
        log.debug("获取调用Token:" + access_token);

        // 查找待获取任务
        String selectSQL = '''Select Rec_Guid, Faxid
                              From Kh_Sw_Sendfax
                             Where Status = 1
                               And (Faxstatus Not In ('8', '9') Or Faxstatus Is Null Or Faxstatus = '')
                               And Result_Count < Result_Countlimit
                               And (Dateadd(Ss, 30 * Result_Count, Lasttrydatetime) < Getdate() Or Lasttrydatetime Is Null Or Lasttrydatetime = '')
                             Order By Lasttrydatetime Desc, Result_Count''';
        List getSmsSelectSQL = eliteBean.chaxun_sql(selectSQL, "dataSource");
        log.debug("SQL获取待获取数据量:" + getSmsSelectSQL.size());

        for (int i = 0; i < getSmsSelectSQL.size(); i++) {

            Map selectResultcm = getSmsSelectSQL.get(i);
            String Rec_Guid = selectResultcm.get("Rec_Guid");
            String Faxid = selectResultcm.get("Faxid");

            // 查出传真发送的地址
            Map<String, String> headParams = new HashMap<String, String>();
            headParams.put("Content-Type", "application/x-www-form-urlencoded");

            Map<String, String> callParams = new HashMap<String, String>();
            callParams.put("token", access_token);
            callParams.put("faxid", Faxid);

            String callBody = KHUtil.urlencode(callParams, "");
            String sendResult = Util.doHttpPostUseHead(KHDBConfig.getAPIURL(eliteBean, "FAX-resultURL"), callBody, "UTF-8", 120000, 0, headParams);
            log.debug("传真-获取发送结果【结果】:" + sendResult);

            JSONObject sendJson = new JSONObject();
            int failCode = -99;
            String failDesc = "";
            try {
                sendJson = JSONObject.fromObject(sendResult);

                failCode = sendJson.getInt("code");
                failDesc = sendJson.getString("msg");
            } catch (Exception e) {
                failCode = -99;
                failDesc = "内部调用传真系统接口返回异常-详情请查看日志";
                log.error(failDesc + e.getMessage());
            }

            if (failCode == 0) {
                // 发送成功
                String faxstatus = sendJson.getJSONObject("data").getString("faxstatus");
                String errcode = sendJson.getJSONObject("data").getString("errcode");
                eliteBean.update("Update Kh_Sw_Sendfax Set result_code = '" + failCode + "', result_description = '" + failDesc + "',  result_count = result_count + 1, result_json = '" + sendResult + "', faxstatus = '" + faxstatus + "', errcode = '" + errcode + "' Where Rec_Guid = '" + Rec_Guid + "'", "dataSource");
            } else {
                // 发送失败
                eliteBean.update("Update Kh_Sw_Sendfax Set result_code = '" + failCode + "', result_description = '" + failDesc + "', result_count = result_count + 1, result_json = '" + sendResult + "' Where Rec_Guid = '" + Rec_Guid + "'", "dataSource");
            }

        }
    }

    public static JSONObject uploadFile(EliteBean eliteBean, String url, String token, Map selectResultcm) {

        // 定义返回对象
        JSONObject resultj = JSONObject.fromObject("{\"code\":-1,\"msg\":\"\"}");
        JSONObject resultd = JSONObject.fromObject("{\"sid\":\"\"}");

        try {
            // 解析当前的待发送内容
            String Subject = selectResultcm.get("Subject");
            String Faxnumber = selectResultcm.get("Faxnumber");
            String Faxnumberext = selectResultcm.get("Faxnumberext");
            String Rawfile = selectResultcm.get("Rawfile");
            String Firstpage = selectResultcm.get("Firstpage");
            String Lastpage = selectResultcm.get("Lastpage");
            String Qr = selectResultcm.get("Qr");

            log.debug("调用发送Fax内容Subject:" + Subject + " Faxnumber:" + Faxnumber + " Faxnumberext:" + Faxnumberext + " Rawfile:" + Rawfile);

            try {
                if (Rawfile.indexOf(",http:") >= 0) {
                    JSONArray fileArr1 = JSONArray.fromObject(Rawfile);
                    List<Map<String, String>> fileList = new ArrayList<>();
                    for (int j = 0; j < fileArr1.size(); j++) {
                        log.debug("当前处理数组对象-" + fileArr1.getJSONObject(j));
                        String[] tempURL = fileArr1.getJSONObject(j).getString("url").split(",");
                        log.debug("当前处理文件地址分割后长度-" + tempURL.length);
                        for (int k = 0; k < tempURL.length; k++) {
                            Map<String, String> tempU = new HashMap<>();
                            tempU.put("url", tempURL[k]);
                            fileList.add(tempU);
                        }
                    }
                    Rawfile = Util.getJsonArrayFromList(fileList).toString();
                    log.debug("综调系统调用的文件数据格式需要预处理...处理后结果:" + Rawfile);
                } else {
                    log.debug("综调系统调用的文件数据格式不需要预处理...");
                }

            } catch (Exception e) {
                log.error("附件类表数据保护:", e);
            }

            // 检查总待发送文件数量
            String sid = ""
            String smsg = ""
            try {
                // 将文件缓存本地
                ContentType contentType = ContentType.create(HTTP.PLAIN_TEXT_TYPE, HTTP.UTF_8);

                Map<String, ContentBody> reqParam = new HashMap<String, ContentBody>();
                reqParam.put("token", new StringBody(token, contentType));
                reqParam.put("subject", new StringBody(Subject, contentType));
                reqParam.put("faxnumber", new StringBody(Faxnumber, contentType));
                reqParam.put("faxnumberext", new StringBody(Faxnumberext, contentType));

                // 待传送文件处理
                JSONArray fileArr = JSONArray.fromObject(Rawfile);

                //处理涉及多附件的模式
                for (int j = 0; j < fileArr.size(); j++) {

                    // 将文件缓存本地
                    String fileThURL = fileArr.getJSONObject(j).getString("url");
                    String fileURL = URLDecoder.decode(fileThURL, "UTF-8");
                    String FaxTMF = KHDBConfig.getParam(eliteBean, "FaxTMF");
                    FaxTMF = KHUtil.isNull(FaxTMF) ? "C:\\" : FaxTMF;
                    log.debug("文件下载路径：" + FaxTMF);

                    String saveFile = httpDownloadFile(fileURL, null, null, FaxTMF);
                    log.debug("文件下载结果：" + saveFile);

                    // 读取文件
                    File file = new File(saveFile);
                    String mimeType = new MimetypesFileTypeMap().getContentType(file);
                    log.debug("文件MimeType：" + mimeType);

                    reqParam.put("rawfile" + j, new FileBody(file, mimeType));
                }

                String httpRes = HttpClientUtil.postFileMultiPart(url, reqParam);
                log.debug("调用发送Fax结果:" + httpRes);

                // 解析发送返回结果
                JSONObject httpResJson = JSONObject.fromObject(httpRes);
                if (httpResJson.containsKey("code")) {
                    int code = httpResJson.getInt("code");
                    if (code == 0) {
                        sid = httpResJson.getJSONObject("data").getString("sid");

                        resultd.put("sid", sid);
                        resultj.put("code", 1);
                        resultj.put("data", resultd);

                    } else {
                        smsg = "调用返回结果不成功,返回对象code值:" + code + " 错误描述:" + httpResJson.getString("msg");
                        resultj.put("msg", smsg);
                    }
                } else {
                    smsg = "调用返回数据不合法,返回对象未含有code参数";
                    resultj.put("msg", smsg);
                }

            } catch (Exception e) {
                log.error("调用发送Fax异常:", e);
                smsg = "发送传真异常,请查看详细日志" + e.getMessage();
                resultj.put("msg", smsg);
            }


        } catch (Exception e) {
            log.error("调用发送Fax异常:", e);
            resultj.put("code", -1);
            resultj.put("msg", "发送传真异常,请查看详细日志" + e.getMessage());
        }
        log.debug("调用发送Fax全部结果:" + resultj.toString());

        return resultj;
    }

    public static String httpDownloadFile(String url, Map<String, String> headers, String encode, String savePath) {

        log.debug("httpDownloadFile url:" + url + " savePath:" + savePath);

        if (encode == null) {
            encode = "utf-8";
        }
        CloseableHttpResponse httpResponse = null;
        CloseableHttpClient closeableHttpClient = null;

        FileOutputStream fs = null;
        InputStream inputStream = null;
        String saveFile = "";
        String filename = "";
        int bytesum = 0;
        int byteread = 0;

        try {
            closeableHttpClient = HttpClientBuilder.create().build();
            HttpGet httpGet = new HttpGet(url);
            //设置header
            if (headers != null && headers.size() > 0) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpGet.setHeader(entry.getKey(), entry.getValue());
                }
            }

            httpResponse = closeableHttpClient.execute(httpGet);

            try {
                filename = URLDecoder.decode(httpResponse.getHeaders("Content-Disposition")[0].getValue().substring(21), "UTF-8").replace("\"", "");
                inputStream = httpResponse.getEntity().getContent();

                saveFile = savePath + "/" + KHUtil.getRandomString(6).toUpperCase(Locale.ROOT) + "_" + filename;
                fs = new FileOutputStream(saveFile);
                byte[] buffer = new byte[1204];

                while ((byteread = inputStream.read(buffer)) != -1) {
                    bytesum += byteread;
                    fs.write(buffer, 0, byteread);
                }
                System.out.println(filename);
            } catch (Exception e) {
                log.error("httpDownloadFile 下载文件异常1", e);
            }

        } catch (Exception e) {
            log.error("httpDownloadFile 下载文件异常2", e);
        } finally {
            try {
                //关闭连接、释放资源
                httpResponse.close();
            } catch (IOException e) {
                log.warn("httpDownloadFile httpResponse.close()异常" + e.getMessage());
            }
            try {
                //关闭连接、释放资源
                inputStream.close();
            } catch (IOException e) {
                log.warn("httpDownloadFile inputStream.close()异常" + e.getMessage());
            }
            try {
                //关闭连接、释放资源
                fs.close();
            } catch (IOException e) {
                log.warn("httpDownloadFile fs.close异常" + e.getMessage());
            }
            try {
                //关闭连接、释放资源
                closeableHttpClient.close();
            } catch (IOException e) {
                log.warn("httpDownloadFile closeableHttpClient.close()异常" + e.getMessage());
            }
        }

        log.debug("当前文件下载路径:" + saveFile);
        return saveFile;
    }

}